<template>
  <div class="chart-container">
    <div v-show="!isLoading" ref="barChart" class="chart-canvas"></div>
    <div v-show="isLoading" class="loading-overlay">
      <div class="loading-content">
        <i class="el-icon-loading"></i>
        <span>数据加载中...</span>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts';
import { sseManager } from '@/api/tool/sse-manager.js';
import { debounce } from 'lodash-es';

const COLOR_LIST = [
  '#C1232B', '#B5C334', '#FCCE10', '#E87C25', '#27727B',
  '#FE8463', '#9BCA63', '#FAD860', '#F3A43B', '#60C0DD'
];

export default {
  data() {
    return {
      chart: null,
      unsubscribe: null,
      isLoading: true,
      currentData: { xAxis: [], series: [] },
      isFirstRender: true // 标记是否是首次渲染
    };
  },
  mounted() {
    this.initChart();
    this.subscribeSSE();
    this.addResizeListener();
  },
  beforeDestroy() {
    this.cleanup();
  },
  methods: {
    /** 初始化图表 */
    async initChart() {
      try {
        await this.$nextTick();
        const container = this.$refs.barChart;
        if (!container) throw new Error('图表容器未找到');

        this.chart = echarts.init(container);
        this.setBaseOption();
      } catch (error) {
        console.error('[BarChart] 初始化失败:', error);
        this.isLoading = false;
      }
    },

    /** 设置基础配置 */
    setBaseOption() {
      this.chart.setOption({
        grid: {
          left: '5%',
          right: '5%',
          top: '15%',
          bottom: '15%',
          containLabel: true
        },
        title: {
          text: '各类型房源销售量（月）',
          left: 'center',
          textStyle: {
            fontSize: 16,
            fontWeight: 'bold',
            color: '#2c3e50'
          }
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
            shadowStyle: {
              color: 'rgba(150,150,150,0.1)'
            }
          }
        },
        xAxis: {
          type: 'category',
          axisLabel: {
            rotate: 45,
            interval: 0,
            width: 80,
            overflow: 'truncate',
            fontSize: 12,
            formatter: (value) => {
              return value.length > 6 ? value.substring(0,6)+'...' : value;
            }
          },
          axisTick: {
            show: false
          },
          axisLine: {
            lineStyle: {
              color: '#999'
            }
          }
        },
        yAxis: {
          type: 'value',
          name: '销售量（套）',
          nameTextStyle: {
            fontSize: 12,
            padding: [0, 0, 0, 30]
          },
          axisLabel: {
            fontSize: 12,
            margin: 15
          },
          splitLine: {
            lineStyle: {
              type: 'dashed',
              color: '#eee'
            }
          },
          min: 0
        },
        animationDuration: 1000,
        animationEasing: 'elasticOut',
        animationDurationUpdate: 800,
        series: [{
          type: 'bar',
          barMaxWidth: 40,
          itemStyle: {
            color: (params) => COLOR_LIST[params.dataIndex % COLOR_LIST.length],
            borderRadius: [6, 6, 0, 0]
          },
          label: {
            show: true,
            position: 'top',
            fontSize: 12,
            color: '#666',
            formatter: '{c}套'
          }
        }]
      });
    },

    /** 订阅SSE数据 */
    subscribeSSE() {
      const updateHandler = (data) => {
        if (this.isLoading) {
          this.isLoading = false;
          this.chart?.hideLoading();
        }

        if (this.validateData(data)) {
          this.processData(data);
        }
      };

      this.unsubscribe = sseManager.subscribe(
        'house_sales',
        debounce(updateHandler, 200),
        {
          onError: () => {
            this.isLoading = true;
            this.chart?.showLoading();
          }
        }
      );
    },

    /** 处理数据更新 */
    processData(rawData) {
      const cleanedData = this.cleanData(rawData);
      const newCategories = Object.keys(cleanedData);
      const newValues = Object.values(cleanedData);

      // 计算最大值并设置Y轴上限
      const maxValue = Math.max(...newValues, 0);
      const yAxisMax = Math.ceil(maxValue * 1.2);

      // 构造带动画的series数据
      const animatedData = newCategories.map((category, index) => {
        let fromValue = 0;

        if (!this.isFirstRender) {
          const oldIndex = this.currentData.xAxis.indexOf(category);
          fromValue = oldIndex !== -1
            ? this.currentData.series[oldIndex]?.value || 0
            : 0;
        }

        return {
          name: category,
          value: cleanedData[category],
          itemStyle: {
            opacity: 0.9
          },
          transition: {
            from: fromValue,
            duration: this.isFirstRender ? 1000 : 800,
            easing: this.isFirstRender ? 'elasticOut' : 'cubicOut'
          }
        };
      });

      // 首次加载：先设为0，再触发真实值动画
      if (this.isFirstRender) {
        this.chart.setOption({
          series: [{
            data: newCategories.map(() => ({ value: 0 }))
          }]
        });

        setTimeout(() => {
          this.updateChart(newCategories, animatedData, yAxisMax);
          this.isFirstRender = false;
        }, 100);
      } else {
        this.updateChart(newCategories, animatedData, yAxisMax);
      }
    },

    /** 更新图表核心逻辑 */
    updateChart(categories, data, yAxisMax) {
      this.chart.setOption({
        xAxis: { data: categories },
        yAxis: { max: yAxisMax },
        series: [{
          data: data,
          barWidth: this.calculateBarWidth(categories.length)
        }]
      }, {
        notMerge: false,
        lazyUpdate: false
      });

      this.currentData = {
        xAxis: categories,
        series: data
      };

      this.$nextTick(() => {
        this.chart?.resize();
      });
    },
    /** 计算柱条宽度 */
    calculateBarWidth(dataLength) {
      const baseWidth = 40;
      const maxWidth = 50;
      const minWidth = 25;
      return Math.max(
        minWidth,
        Math.min(maxWidth, baseWidth - dataLength)
      );
    },

    /** 数据清洗 */
    cleanData(rawData) {
      return Object.keys(rawData).reduce((cleaned, key) => {
        const cleanKey = key.replace(/套/g, '').trim();
        cleaned[cleanKey] = Math.max(Number(rawData[key]) || 0, 0);
        return cleaned;
      }, {});
    },

    /** 数据验证 */
    validateData(data) {
      return (
        typeof data === 'object' &&
        !Array.isArray(data) &&
        Object.values(data).every(v => !isNaN(Number(v)))
      );
    },

    /** 窗口缩放处理 */
    addResizeListener() {
      this.debouncedResize = debounce(() => {
        this.chart?.resize();
      }, 300);
      window.addEventListener('resize', this.debouncedResize);
    },

    /** 清理资源 */
    cleanup() {
      if (this.unsubscribe) this.unsubscribe();
      if (this.chart) {
        this.chart.dispose();
        this.chart = null;
      }
      window.removeEventListener('resize', this.debouncedResize);
    }
  }
};
</script>

<style scoped>
/* 图表容器样式 */
.chart-container {
  position: relative;
  width: 100%;
  height: 500px;
  padding: 0px;
  background: #fff;
  border-radius: 8px;
}

/* 图表画布样式 */
.chart-canvas {
  width: 100%;
  height: 100%;
  min-width: 500px;
}

/* 加载层样式（覆盖在图表上） */
.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.95);
  z-index: 10;
}

/* 加载提示内容样式 */
.loading-content {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #606266;
  font-size: 16px;
}

/* 加载图标的动画效果 */
.el-icon-loading {
  font-size: 24px;
  animation: rotating 2s linear infinite;
}

/* 定义旋转动画的关键帧 */
@keyframes rotating {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* 响应式设计：在屏幕宽度小于等于768px时应用 */
@media (max-width: 768px) {
  .chart-container {
    height: 400px;
    padding: 10px;
  }

  .chart-canvas {
    min-width: 100%;
  }
}
</style>